package com.devbobcorn.nekoration.blocks;

import java.util.function.ToIntFunction;

import com.devbobcorn.nekoration.Nekoration;
import com.devbobcorn.nekoration.blocks.frames.DyeableWindowFrameBlock;
import com.devbobcorn.nekoration.blocks.frames.DyeableWindowSillBlock;
import com.devbobcorn.nekoration.blocks.frames.DyeableWindowTopBlock;
import com.devbobcorn.nekoration.items.DyeableBlockItem;
import com.devbobcorn.nekoration.items.HalfTimberBlockItem;
import com.devbobcorn.nekoration.items.ModItemGroups;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.block.AbstractBlock.Settings;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.state.property.Properties;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;

public final class ModBlocks {
    public static final Block STONE_LAYERED = new StoneBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F));
    public static final Block STONE_BASE_BOTTOM = new StoneBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F));
    public static final Block STONE_FRAME_BOTTOM = new StoneBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F));
    public static final Block STONE_PILLAR_BOTTOM = new StoneBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F));
    public static final Block STONE_BASE = new StonePillarBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F), DyeableVerticalConnectBlock.ConnectionType.PILLAR, false);
    public static final Block STONE_FRAME = new StonePillarBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F), DyeableVerticalConnectBlock.ConnectionType.PILLAR, false);
    public static final Block STONE_PILLAR = new StonePillarBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F), DyeableVerticalConnectBlock.ConnectionType.PILLAR, false);
    public static final Block STONE_DORIC = new StonePillarBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F), DyeableVerticalConnectBlock.ConnectionType.PILLAR, false);
    public static final Block STONE_IONIC = new StonePillarBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F), DyeableVerticalConnectBlock.ConnectionType.PILLAR, false);
    public static final Block STONE_CORINTHIAN = new StonePillarBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F), DyeableVerticalConnectBlock.ConnectionType.PILLAR, false);

    public static final Block WINDOW_TOP = new DyeableWindowTopBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F).nonOpaque(), DyeableHorizontalConnectBlock.ConnectionType.TRIPLE, false);
    public static final Block WINDOW_SILL = new DyeableWindowSillBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F).nonOpaque(), DyeableHorizontalConnectBlock.ConnectionType.BEAM, false);
    public static final Block WINDOW_PLANT = new DyeableHorizontalConnectBlock(Settings.of(Material.LEAVES).strength(0.0F).nonOpaque(), DyeableHorizontalConnectBlock.ConnectionType.BEAM, false);
    public static final Block WINDOW_FRAME = new DyeableWindowFrameBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F).nonOpaque());

    public static final Block STONE_POT = new PotBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F).nonOpaque(), 6.0D);
    public static final Block STONE_PLANTER = new PotBlock(Settings.of(Material.STONE).strength(1.5F, 6.0F).nonOpaque(), 8.0D);

    public static final Block HALF_TIMBER_P0 = new HalfTimberBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F));
    public static final Block HALF_TIMBER_P1 = new HalfTimberBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F));
    public static final Block HALF_TIMBER_P2 = new HalfTimberBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F));
    public static final Block HALF_TIMBER_P3 = new HalfTimberBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F));
    public static final Block HALF_TIMBER_P4 = new HalfTimberBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F));
    public static final Block HALF_TIMBER_P5 = new HalfTimberBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F));
    public static final Block HALF_TIMBER_P6 = new HalfTimberBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F));
    public static final Block HALF_TIMBER_P7 = new HalfTimberBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F));
    public static final Block HALF_TIMBER_P8 = new HalfTimberBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F));
    public static final Block HALF_TIMBER_P9 = new HalfTimberBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F));
    public static final Block HALF_TIMBER_PILLAR_P0 = new HalfTimberPillarBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F), HalfTimberPillarBlock.ConnectionType.PILLAR, false);
    public static final Block HALF_TIMBER_PILLAR_P1 = new HalfTimberPillarBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F), HalfTimberPillarBlock.ConnectionType.TRIPLE, false);
    public static final Block HALF_TIMBER_PILLAR_P2 = new HalfTimberPillarBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F), HalfTimberPillarBlock.ConnectionType.TRIPLE, false);

    public static final Block DOOR_1 = new DyeableDoorBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F).nonOpaque());
    public static final Block DOOR_2 = new DyeableDoorBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F).nonOpaque());
    public static final Block DOOR_3 = new DyeableDoorBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F).nonOpaque());
    public static final Block DOOR_TALL_1 = new DyeableDoorBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F).nonOpaque(), true);
    public static final Block DOOR_TALL_2 = new DyeableDoorBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F).nonOpaque(), true);
    public static final Block DOOR_TALL_3 = new DyeableDoorBlock(Settings.of(Material.WOOD).strength(2.0F, 3.0F).nonOpaque(), true);

    public static final Block AWNING_PURE = new AwningBlock(Settings.of(Material.WOOL).strength(0.8F));
    public static final Block AWNING_STRIPE = new AwningBlock(Settings.of(Material.WOOL).strength(0.8F));
    public static final Block AWNING_PURE_SHORT = new ShortAwningBlock(Settings.of(Material.WOOL).strength(0.8F));
    public static final Block AWNING_STRIPE_SHORT = new ShortAwningBlock(Settings.of(Material.WOOL).strength(0.8F));

    public static final Block CANDLE_HOLDER_IRON = new CandleHolderBlock(Settings.of(Material.METAL).strength(5.0F, 6.0F).luminance(candleHolderEmission(15)).nonOpaque());
    public static final Block CANDLE_HOLDER_GOLD = new CandleHolderBlock(Settings.of(Material.METAL).strength(3.0F, 6.0F).luminance(candleHolderEmission(15)).nonOpaque());
    public static final Block CANDLE_HOLDER_QUARTZ = new CandleHolderBlock(Settings.of(Material.STONE).strength(0.8F).luminance(candleHolderEmission(15)).nonOpaque());

    public static ToIntFunction<BlockState> candleHolderEmission(int lightlevel) {
        return (state) -> {
            return state.get(Properties.AGE_3) > 0 ? lightlevel : 0;
        };
    }

    public static void registerAll() {
        register("stone_layered", STONE_LAYERED);
        register("stone_base_bottom", STONE_BASE_BOTTOM);
        register("stone_frame_bottom", STONE_FRAME_BOTTOM);
        register("stone_pillar_bottom", STONE_PILLAR_BOTTOM);
        register("stone_base", STONE_BASE);
        register("stone_frame", STONE_FRAME);
        register("stone_pillar", STONE_PILLAR);
        register("stone_doric", STONE_DORIC);
        register("stone_ionic", STONE_IONIC);
        register("stone_corinthian", STONE_CORINTHIAN);

        register("window_top", WINDOW_TOP);
        register("window_sill", WINDOW_SILL);
        register("window_plant", WINDOW_PLANT);
        register("window_frame", WINDOW_FRAME);

        register("stone_pot", STONE_POT);
        register("stone_planter", STONE_PLANTER);

        register("half_timber_p0", HALF_TIMBER_P0);
        register("half_timber_p1", HALF_TIMBER_P1);
        register("half_timber_p2", HALF_TIMBER_P2);
        register("half_timber_p3", HALF_TIMBER_P3);
        register("half_timber_p4", HALF_TIMBER_P4);
        register("half_timber_p5", HALF_TIMBER_P5);
        register("half_timber_p6", HALF_TIMBER_P6);
        register("half_timber_p7", HALF_TIMBER_P7);
        register("half_timber_p8", HALF_TIMBER_P8);
        register("half_timber_p9", HALF_TIMBER_P9);
        register("half_timber_pillar_p0", HALF_TIMBER_PILLAR_P0);
        register("half_timber_pillar_p1", HALF_TIMBER_PILLAR_P1);
        register("half_timber_pillar_p2", HALF_TIMBER_PILLAR_P2);

        register("door_1", DOOR_1);
        register("door_2", DOOR_2);
        register("door_3", DOOR_3);
        register("door_tall_1", DOOR_TALL_1);
        register("door_tall_2", DOOR_TALL_2);
        register("door_tall_3", DOOR_TALL_3);

        register("awning_pure", AWNING_PURE);
        register("awning_stripe", AWNING_STRIPE);
        register("awning_pure_short", AWNING_PURE_SHORT);
        register("awning_stripe_short", AWNING_STRIPE_SHORT);

        register("candle_holder_iron", CANDLE_HOLDER_IRON);
        register("candle_holder_gold", CANDLE_HOLDER_GOLD);
        register("candle_holder_quartz", CANDLE_HOLDER_QUARTZ);
    }

    private static void register(String name, Block block) {
        register(name, block, true);
    }

    private static void register(String name, Block block, boolean hasItem) {
        Registry.register(Registry.BLOCK, getId(name), block);

        if (hasItem) {
            Item.Settings properties = new Item.Settings().group(ModItemGroups.DECOR_GROUP);
            BlockItem blockItem;
            /* if (block instanceof TableBlock || block instanceof ChairBlock){
                // Classes: HalfTimberBlock / HalfTimberPillarBlock
                properties = new Item.Settings().group(ModItemGroups.DECOR_GROUP);
                blockItem = new BlockItem(block, properties);
            } else*/ if (block instanceof HalfTimberBlock || block instanceof HalfTimberPillarBlock){
                // Classes: HalfTimberBlock / HalfTimberPillarBlock
                properties = new Item.Settings().group(ModItemGroups.WOODEN_GROUP);
                blockItem = new HalfTimberBlockItem(block, properties);
            }/* else if (block instanceof WindowBlock || block instanceof DyeableWoodenBlock || block instanceof DyeableHorizontalWoodenBlock){
                properties = new Item.Settings().group(block instanceof WindowBlock ? ModItemGroups.WINDOW_N_DOOR_GROUP : ModItemGroups.DECOR_GROUP);
                blockItem = new DyeableWoodenBlockItem(block, properties);
            }*/ else if (block instanceof StoneBlock || block instanceof StonePillarBlock){
                properties = new Item.Settings().group(ModItemGroups.STONE_GROUP);
                blockItem = new DyeableBlockItem(block, properties);
            } else out:if (block instanceof DyeableBlock || block instanceof DyeableHorizontalConnectBlock){
                if (block instanceof CandleHolderBlock){
                    properties = new Item.Settings().group(ModItemGroups.DECOR_GROUP);
                    blockItem = new DyeableBlockItem(block, properties, false);
                    break out;
                } else if (block instanceof DyeableHorizontalBlock) {
                    if (block instanceof AwningBlock || block instanceof ShortAwningBlock || block == ModBlocks.WINDOW_PLANT) // Awning...
                        properties = new Item.Settings().group(ModItemGroups.DECOR_GROUP);
                    else properties = new Item.Settings().group(ModItemGroups.WINDOW_N_DOOR_GROUP); // Window Frame...
                } else properties = new Item.Settings().group(ModItemGroups.DECOR_GROUP);
                blockItem = new DyeableBlockItem(block, properties);
            } else {
                if (block instanceof DyeableDoorBlock)
                    properties = new Item.Settings().group(ModItemGroups.WINDOW_N_DOOR_GROUP);
                else properties = new Item.Settings().group(ModItemGroups.DECOR_GROUP);
                blockItem = new BlockItem(block, properties);
            }
            //And register it...
            Registry.register(Registry.ITEM, getId(name), blockItem);
        }
    }

    private static Identifier getId(String name) {
        return new Identifier(Nekoration.MODID, name);
    }
}
